#include "mythread.h"
#include <QDebug>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <QDebug>
#include "temp.h"
#include <stdio.h>
using namespace std;
using namespace cv;


//Global variables
Rect box;
bool drawing_box = false;
bool gotBB = false;
bool tl = true;
bool rep = false;
bool fromfile=false;
string video;

//Mat rotateImg;
//Mat rotateImg_temp;
//Mat rotateImg_temp_xuan;
//BoundingBox xg_box;
//Mat current_gray;


QString filenamePATH;
unsigned char* src_img;

void readBB(char* file){
  ifstream bb_file (file);
  string line;
  getline(bb_file,line);
  istringstream linestream(line);
  string x1,y1,x2,y2;
  getline (linestream,x1, ',');
  getline (linestream,y1, ',');
  getline (linestream,x2, ',');
  getline (linestream,y2, ',');
  int x = atoi(x1.c_str());// = (int)file["bb_x"];
  int y = atoi(y1.c_str());// = (int)file["bb_y"];
  int w = atoi(x2.c_str())-x;// = (int)file["bb_w"];
  int h = atoi(y2.c_str())-y;// = (int)file["bb_h"];

//  box = Rect(x,y,w,h);
}
//bounding box mouse callback
void mouseHandler(int event, int x, int y, int flags, void *param){
  switch( event ){
  case CV_EVENT_MOUSEMOVE:
    if (drawing_box){
        box.width = x-box.x;
        box.height = y-box.y;
    }
    break;
  case CV_EVENT_LBUTTONDOWN:
    drawing_box = true;
    box = Rect( x, y, 0, 0 );
    break;
  case CV_EVENT_LBUTTONUP:
    drawing_box = false;
    if( box.width < 0 ){
        box.x += box.width;
        box.width *= -1;
    }
    if( box.height < 0 ){
        box.y += box.height;
        box.height *= -1;
    }
    gotBB = true;
    break;
  }
}

void print_help(char** argv){
  printf("use:\n     %s -p /path/parameters.yml\n",argv[0]);
  printf("-s    source video\n-b        bounding box file\n-tl  track and learn\n-r     repeat\n");
}

void read_options(int argc, char** argv,VideoCapture& capture,FileStorage &fs){
  for (int i=0;i<argc;i++){
//      if (strcmp(argv[i],"-b")==0)
      {
          if (argc>i){
//              readBB(argv[i+1]);
//              readBB("init.txt");
              gotBB = true;
          }
          else
          {
//            print_help(argv);
          }
      }
//      if (strcmp(argv[i],"-s")==0)
      {
          if (argc>i)
          {
//              video = string(argv[i+1]);
//              video = string("live2_ok.avi");
//              video = string("D://Qt5.9.0//qtexample//build-opencv_test-Desktop_Qt_5_9_0_MinGW_32bit-Debug//live2_ok.avi");
              filenamePATH = QDir::toNativeSeparators(filenamePATH);;
              qDebug()<<"filenamePATH:"<<filenamePATH;
              video = filenamePATH.toStdString();
              capture.open(video);
              fromfile = true;
          }
          else
          {
//            print_help(argv);
          }
      }
//      if (strcmp(argv[i],"-p")==0)
      {
          if (argc>i)
          {
//              fs.open(argv[i+1], FileStorage::READ);
              fs.open("parameters.yml", FileStorage::READ);

          }
          else
          {
            print_help(argv);
          }
      }
//      if (strcmp(argv[i],"-no_tl")==0){
//          tl = false;
//      }
//      if (strcmp(argv[i],"-r")==0){
//          rep = true;
//      }
  }
}

void myThread::set_filename(QString name)
{
    filenamePATH = name;
}

myThread::myThread(QObject *parent) : QThread(parent)
{
    while_flag = true;
    win_num = 0;
    src_img =  (unsigned char*)malloc(2048 * 2048);
    init();
}


void myThread::run()
{
    qDebug("run~~~!");
    tld_run();
}

void myThread::thr_stop()
{
    while_flag = false;
}

void myThread::set_autoctr(int num)
{
    auto_control = num;
}

int myThread::tld_run()
{
    TLD tld;
    BoundingBox xg_box;
    Mat current_gray;

    win_num++;
    while_flag = true;
    VideoCapture capture;

    FileStorage fs;
    //Read options
    char** argv;
    read_options(2,argv,capture,fs);

    //Init camera
    if (!capture.isOpened())
    {
      cout << "capture device failed to open!" << endl;
      return 1;
    }


    int frame_fps = 27;
    int isColor = 1;
    //要保存的视频 高 和 宽
    int frame_width = W_WIDTH;
    int frame_height = H_HEIGHT;
    VideoWriter writer = VideoWriter("./out_TRACK.avi", CV_FOURCC('D', 'I', 'V', 'X'), frame_fps, Size(frame_width, frame_height), isColor);

//    namedWindow("ncc", 0);

    //Read parameters file
    tld.read(fs.getFirstTopLevelNode());
    Mat frame;
    Mat last_gray;
    Mat first;

    if (fromfile)
    {
        capture >> frame;
        cvtColor(frame, last_gray, CV_RGB2GRAY);
        frame.copyTo(first);
    }
    else
    {
        capture.set(CV_CAP_PROP_FRAME_WIDTH,2048);
        capture.set(CV_CAP_PROP_FRAME_HEIGHT,2048);
    }

    GETBOUNDINGBOX:
    gotBB = true;
    while(!gotBB)
    {
        if(!while_flag)
        {
          return 0;
        }
        if (!fromfile)
        {
        capture >> frame;
        }
        else
        first.copyTo(frame);
        cvtColor(frame, last_gray, CV_RGB2GRAY);
        drawBox(frame,box, Scalar::all(0), 2);
//              imshow("tld", frame);
        QImage img((const unsigned char *)(frame.data), frame.cols, frame.rows, frame.cols * 3, QImage::Format_RGB888);
        emit send_img(img);
        msleep(30);
//              int key = 0;
//              if((key = waitKeyEx(10)) >= 0)
//              {
//                  if(key == 'q')
//                  {
//                      break;
//                  }
//              }
    }

    if (min(box.width,box.height)<(int)fs.getFirstTopLevelNode()["min_win"])
    {
        cout << "Bounding box too small, try again." << endl;
//        gotBB = false;
//        goto GETBOUNDINGBOX;
    }

    //Output file
    FILE  *bb_file = fopen("bounding_boxes.txt","w");



    //Run-time

    BoundingBox pbox;
    //搜索框
    BoundingBox box_1;
    vector<Point2f> pts1;
    vector<Point2f> pts2;
    bool status=true;
    int frames = 1;
    int detections = 1;

    qDebug()<<"auto_control:"<<auto_control;
    switch (auto_control)
    {

    case 1:
        box.x = 646;
        box.y = 743;
        box.width = 80;
        box.height = 80;
        break;
    case 2:
        box.x = 150;
        box.y = 1092;
        box.width = 80;
        box.height = 80;
        break;
    case 3:
        box.x = 772;
        box.y = 1162;
        box.width = 50;
        box.height = 50;
        break;
    case 4:
        box.x = 1350;
        box.y = 1253;
        box.width = 70;
        box.height = 70;
        break;
    case 5:
//        box.x = 600;
//        box.y = 250;
//        box.width = 80;
//        box.height = 150;
        box.x = 600;
        box.y = 250;
        box.width = 80;
        box.height = 150;
        break;
    case 6:
//        box.x = 600;
//        box.y = 250;
//        box.width = 80;
//        box.height = 150;
        box.x = 1120;
        box.y = 926;
        box.width = 50;
        box.height = 50;
        break;
    default:
        break;
    }

qDebug("x:%d y:%d w:%d h:%d", box.x, box.y, box.width, box.height);
    box_1.x = box.x - SEARCH_W / 2;//558;
    box_1.y = box.y - SEARCH_H / 2;//46;
    box_1.width = SEARCH_W;
    box_1.height = SEARCH_H;

    //针对特定图像 的 搜索框 转换 跟踪框坐标
//    box.x = box.x - box_1.x;//558;
//    box.y = box.y - box_1.y;//46;


    while(while_flag)
    {

        capture >> frame;

        memset(src_img, 0, 2048 * 2048);
        cvtColor(frame, first, CV_RGB2GRAY);
        if(first.isContinuous())
        {
            memcpy(src_img, first.data, 2048 * 2048);
        }
        else
        {
            if(src_img != NULL)
            {
                free(src_img);
            }
            return -1;
        }

        NNC_IMAGE_TRACK(src_img, frames, box.x + box.width / 2, box.y + box.height / 2);
        QImage img((const unsigned char *)(frame.data), frame.cols, frame.rows, frame.cols * 3, QImage::Format_RGB888);
        emit send_img(img);

        frames++;
#if 0
        rotateImg = frame(box_1);
        //第一帧为初始化帧
        if(frames == 1)
        {
            //在第一帧上画框
            cvtColor(rotateImg, last_gray, CV_RGB2GRAY);
            drawBox(frame,box, Scalar::all(0), 2);


            //tld初始化
            tld.init(last_gray,box,bb_file);
            //检测计数
            detections++;
            //帧计数
            frames++;
            continue;
        }

        //get frame
        cvtColor(rotateImg, current_gray, CV_RGB2GRAY);
        //Process Frame
        tld.processFrame(last_gray,current_gray,pts1,pts2,pbox,status,tl,bb_file);

        xg_box.x = box_1.x + pbox.x;
        xg_box.y = box_1.y + pbox.y;
        xg_box.width = pbox.width;
        xg_box.height = pbox.height;
        qDebug("%d %d %d %d", xg_box.x, xg_box.y, xg_box.width, xg_box.height);
        //Draw Points
        if (status)
        {
            //      drawPoints(rotateImg,pts1);
            //      drawPoints(rotateImg,pts2,Scalar(0,255,0));
            drawBox(rotateImg,pbox, Scalar::all(0), 2);
            detections++;


            drawBox(frame,xg_box ,Scalar(0, 0, 255), 2);
            //搜索框
            drawBox(frame,box_1 ,Scalar(255, 0, 0), 2);
        }

    //            imshow(win_name.toStdString(), frame);
        QImage img((const unsigned char *)(frame.data), frame.cols, frame.rows, frame.cols * 3, QImage::Format_RGB888);
        emit send_img(img);

        swap(last_gray,current_gray);
        pts1.clear();
        pts2.clear();
        frames++;
        qDebug("Detection rate: %d/%d\n",detections,frames);

        if(frames > 1)
        {
            qDebug("pbox.x:%d  pbox.y:%d\n", pbox.x, pbox.y);
            if((pbox.x < S_SCALE) || (pbox.y < S_SCALE) || (SEARCH_H - (pbox.x + pbox.width) < S_SCALE) || (SEARCH_W - (pbox.y + pbox.height)) < S_SCALE)
            {
                //            printf("box.x:%d y:%d w:%d h:%d\n", pbox.x, pbox.y, pbox.width, pbox.height);
                box_1.x = pbox.x + pbox.width / 2 + box_1.x - SEARCH_W / 2;
                if(box_1.x < 1)
                {
                    box_1.x = 1;
                }

                if(box_1.x > 2048 - SEARCH_W)
                {
                    box_1.x = 2048 - SEARCH_W - 1;
                }
                box_1.y = pbox.y + pbox.height / 2 + box_1.y - SEARCH_H / 2;
                if(box_1.y < 1)
                {
                    box_1.y = 1;
                }
                if(box_1.y > 2048 - SEARCH_H)
                {
                    box_1.y = 2048 - SEARCH_H - 1;
                }
                box_1.width = SEARCH_W;
                box_1.height = SEARCH_H;
                //            printf("box_1.x:%d y:%d w:%d h:%d\n", box_1.x, box_1.y, box_1.width, box_1.height);

                pbox.x = SEARCH_W / 2 - pbox.width / 2;
                pbox.y = SEARCH_H / 2 - pbox.height / 2;
                //            pbox.x = 112;
                //            pbox.y = 112;
            }
        }
        int key = 0;
        if((key = waitKeyEx(10)) >= 0)
        {
            if(key == 'q')
            {
                break;
            }
        }
#endif
    }


    if (rep)
    {
      rep = false;
      tl = false;
      fclose(bb_file);
      bb_file = fopen("final_detector.txt","w");

      capture.release();
      capture.open(video);

    }
//    destroyWindow(win_name.toStdString());
    capture.release();
    fclose(bb_file);
    qDebug("over!!!");
    if(src_img != NULL)
    {
        free(src_img);
    }

}
